package com.sec.android.app.myfiles.navigation;

import com.sec.android.app.myfiles.MyFilesTestRunner;
import com.sec.android.app.myfiles.TestInput;
import com.sec.android.app.myfiles.facade.cmd.ToSelectModeCmd;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.module.abstraction.AbsContentObserverImp;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.CategoryType;
import com.sec.android.app.myfiles.module.download.DownloadFileRecord;
import com.sec.android.app.myfiles.module.local.file.LocalFileRecord;
import com.sec.android.app.myfiles.module.local.recent.RecentFileRecord;
import com.sec.android.app.myfiles.navigation.NavigationInfo.NavigationMode;
import com.sec.android.app.myfiles.shadow.custom.ShadowAppFeatures;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.reflect.internal.WhiteboxImpl;

@RunWith(MyFilesTestRunner.class)
/*@PrepareForTest({
        AppFeatures.class
})*/
public class testNavigationInfo {
    NavigationInfo mNaviInfo;
    FileRecord mRecord;

    @Before
    public void setUp() throws Exception {
        mRecord = FileRecord.createFileRecord(FileRecord.StorageType.Local, "/testRoot/testDir/testFile.txt");
        mNaviInfo = NavigationInfo.getInstance(NavigationInfo.NavigationMode.Normal, mRecord);
        ShadowAppFeatures.mIsTablet = false;
    }

    @After
    public void tearDown() throws Exception {
        ShadowAppFeatures.mIsTablet = false;
    }

    @Test
    public void testGetInstance() {
        Assert.assertNotNull(NavigationInfo.getInstance(mNaviInfo, mRecord));
        Assert.assertNotNull(NavigationInfo.getInstance(NavigationInfo.NavigationMode.Normal, mRecord));
    }

    @Test
    public void testStorageType() {
        Assert.assertEquals(mRecord.getStorageType(), mNaviInfo.getStorageType());
    }

    @Test
    public void testNavigationMode() {
        for (NavigationInfo.NavigationMode mode : NavigationInfo.NavigationMode.values()) {
            mNaviInfo.setNavigationMode(mode);
            Assert.assertEquals(mode, mNaviInfo.getNavigationMode());

            boolean isNormalMode = false;
            boolean isPickerMode = false;
            boolean isSinglePickerMode = false;
            boolean isSelectDestination = false;
            boolean isSelectDestinationPath = false;
            boolean isSelectOpDestination = false;
            boolean isCreateDocument = false;
            boolean isRemoveFromPrivate = false;
            boolean isCompressPreview = false;

            switch (mode) {
                case Normal:
                    isNormalMode = true;
                    break;
                case Pick_files:
                    isPickerMode = true;
                    break;
                case Pick_one_file:
                    isPickerMode = true;
                    isSinglePickerMode = true;
                    break;
                case Select_copy_destination:
                    isSelectDestination = true;
                    isSelectOpDestination = true;
                    break;
                case Select_move_destination:
                    isSelectDestination = true;
                    isSelectOpDestination = true;
                    break;
                case Select_destination_path:
                    isSelectDestination = true;
                    isSelectDestinationPath = true;
                    break;
                case Select_remove_from_private:
                    isSelectDestination = true;
                    isSelectOpDestination = true;
                    isRemoveFromPrivate = true;
                    break;
                case Select_create_doc_destination:
                    isSelectDestination = true;
                    isCreateDocument = true;
                    break;
                case Preview_compress_item:
                    isCompressPreview = true;
                    break;
                case Optimize_storage_files:
                    break;
                case Select_optimize_storage_backup_destination:
                    isSelectDestination = true;
                    isSelectOpDestination = true;
                    break;


            }

            Assert.assertEquals(isNormalMode, mNaviInfo.isNormalMode());
            Assert.assertEquals(isPickerMode, mNaviInfo.isPickerMode());
            Assert.assertEquals(isSinglePickerMode, mNaviInfo.isSinglePickerMode());
            Assert.assertEquals(isSelectDestination, mNaviInfo.isSelectDestination());
            Assert.assertEquals(isSelectDestinationPath, mNaviInfo.isSelectDestinationPath());
            Assert.assertEquals(isSelectOpDestination, mNaviInfo.isSelectOpDestination());
            Assert.assertEquals(isCreateDocument, mNaviInfo.isCreateDocument());
            Assert.assertEquals(isRemoveFromPrivate, mNaviInfo.isRemoveFromPrivate());
            Assert.assertEquals(isCompressPreview, mNaviInfo.isCompressPreview());

        }
    }


    @Test
    public void testIsSingleAudioPickerMode() {
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Pick_one_file, new String[]{"audio/*"}, true);
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Pick_one_file, new String[]{"application/ogg"}, true);
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Pick_one_file, new String[]{"audio/*", "application/ogg"}, true);
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Pick_one_file, new String[]{"audio/mp3", "application/ogg"}, true);
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Pick_one_file, new String[]{"audio/*", "application/*"}, false);
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Pick_files, new String[]{"audio/"}, false);
        testIsSingleAudioPickerMode(NavigationInfo.NavigationMode.Normal, new String[]{"audio/"}, false);
    }

    private void testIsSingleAudioPickerMode(NavigationInfo.NavigationMode mode, String[] mimeType, boolean expected) {
        mNaviInfo.setNavigationMode(mode);
        mNaviInfo.setMimeTypeFilter(mimeType);
        Assert.assertEquals(expected, mNaviInfo.isSingleAudioPickerMode());
    }

    @Test
    public void testIsPickerFilesWithParam() throws Exception {
        for (NavigationMode navigationMode : NavigationMode.values()) {
            TestInput<Boolean>[] testList = TestInput.createTestData(
                    new TestInput<>(false, null, null),
                    new TestInput<>(true, null, new String[]{"Test"}),
                    new TestInput<>(true, CategoryType.Audio, null),
                    new TestInput<>(true, CategoryType.Audio, new String[]{"Test"})
            );

            mNaviInfo.setNavigationMode(navigationMode);

            for (TestInput<Boolean> testValue : testList) {
                mNaviInfo.setCategoryFilter((CategoryType) testValue.get(0));
                mNaviInfo.setMimeTypeFilter((String[]) testValue.get(1));

                boolean bRet = WhiteboxImpl.invokeMethod(mNaviInfo, "isPickerFilesWithParam");
                Boolean expected = false;
                if (navigationMode == NavigationMode.Pick_files) {
                    expected = testValue.expected();
                }

                Assert.assertEquals(expected, bRet);
            }
        }
    }

    @Test
    public void testCurRecord() {
        FileRecord record = FileRecord.createFileRecord(FileRecord.StorageType.Local, "/testRoot/testDir/testFile2.txt");
        mNaviInfo.setCurRecord(record);
        Assert.assertEquals(record, mNaviInfo.getCurRecord());

    }

    @Test
    public void testCurFragment() {
        AbsMyFilesFragment frag = PowerMockito.mock(AbsMyFilesFragment.class);
        mNaviInfo.setCurFragment(frag);
        Assert.assertNotNull(mNaviInfo.getCurFragment());
    }

    @Test
    public void testCurListPosition() {
        int position = 1;
        mNaviInfo.setCurListPosition(position);
        Assert.assertEquals(position, mNaviInfo.getCurListPosition());
    }

    @Test
    public void testFocusRecord() {
        mNaviInfo.setFocusRecord(mRecord);
        Assert.assertEquals(mRecord, mNaviInfo.getFocusRecord());
    }

    @Test
    public void testCategoryFilter() {
        for (CategoryType type : CategoryType.values()) {
            mNaviInfo.setCategoryFilter(type);
            Assert.assertEquals(type, mNaviInfo.getCategoryFilter());
        }
    }

    @Test
    public void testMimeType() {
        String[] mime = {"TestMimeType"};
        mNaviInfo.setMimeTypeFilter(mime);
        Assert.assertEquals(mime, mNaviInfo.getMimeTypeFilter());
    }

    @Test
    public void testExtensionFilter() {
        String[] ext = {"TestExtension"};
        mNaviInfo.setExtensionFilter(ext);
        Assert.assertEquals(ext, mNaviInfo.getExtensionFilter());
    }

    @Test
    public void testPathFilter() {
        String filter = "TestFilder";
        mNaviInfo.setPathFilter(filter);
        Assert.assertEquals(filter, mNaviInfo.getPathFilter());
    }

    @Test
    public void testPrefixFilter() {
        String filter = "TestPrefixFilder";
        mNaviInfo.setPrefixFilter(filter);
        Assert.assertEquals(filter, mNaviInfo.getPrefixFilter());
    }

    @Test
    public void testMaxSelectCnt() {
        int cnt = 2;
        mNaviInfo.setMaxSelectCnt(cnt);
        Assert.assertEquals(cnt, mNaviInfo.getMaxSelectCnt());
    }

    @Test
    public void testStartWithSelectMode() {
        mNaviInfo.setStartWithSelectMode(ToSelectModeCmd.SelectModeType.SELECT_MODE);
        Assert.assertEquals(ToSelectModeCmd.SelectModeType.SELECT_MODE, mNaviInfo.getStartWithSelectMode());
    }

    @Test
    public void testIsNavigationModeChanged() {
        TestInput<Boolean>[] testList = TestInput.createTestData(
                new TestInput<>(false, NavigationMode.Pick_files, new LocalFileRecord("/test")),
                new TestInput<>(false, mNaviInfo.getNavigationMode(), new LocalFileRecord("/test")),
                new TestInput<>(false, mNaviInfo.getNavigationMode(), mNaviInfo.getCurRecord()),
                new TestInput<>(true, NavigationMode.Pick_files, mNaviInfo.getCurRecord())
        );

        for (TestInput<Boolean> testData : testList) {
            NavigationInfo input = NavigationInfo.getInstance((NavigationMode) testData.get(0), (FileRecord) testData.get(1));
            Boolean actual = mNaviInfo.isNavigationModeChanged(input);
            Assert.assertEquals(testData.expected(), actual);
        }
    }


    @Test
    public void testIsLeftPanelDisabled() throws Exception {
        testIsLeftPanelDisabledPhone();
        testIsLeftPanelDisabledTablet();
    }

    private void testIsLeftPanelDisabledTablet() throws Exception {

        ShadowAppFeatures.mIsTablet = true;

        for (NavigationMode navigationMode : NavigationMode.values()) {
            TestInput<Boolean>[] testList = TestInput.createTestData(
                    new TestInput<>(false, null, null),
                    new TestInput<>(true, null, new String[]{"Test"}),
                    new TestInput<>(true, CategoryType.Audio, null),
                    new TestInput<>(true, CategoryType.Audio, new String[]{"Test"})
            );

            mNaviInfo.setNavigationMode(navigationMode);

            for (TestInput<Boolean> testValue : testList) {
                mNaviInfo.setCategoryFilter((CategoryType) testValue.get(0));
                mNaviInfo.setMimeTypeFilter((String[]) testValue.get(1));

                boolean bRet = WhiteboxImpl.invokeMethod(mNaviInfo, "isLeftPanelDisabled");
                Boolean expected = false;
                if (navigationMode == NavigationMode.Pick_files) {
                    expected = testValue.expected();
                } else if (navigationMode == NavigationMode.Pick_one_file) {
                    expected = true;
                }

                Assert.assertEquals(expected, bRet);
            }
        }
    }


    private void testIsLeftPanelDisabledPhone() {
        NavigationMode[] trueList = new NavigationMode[]{
                NavigationMode.Select_copy_destination,
                NavigationMode.Select_move_destination,
                NavigationMode.Select_destination_path,
                NavigationMode.Select_remove_from_private,
                NavigationMode.Select_create_doc_destination,
                NavigationMode.Pick_one_file,
                NavigationMode.Pick_files,
                NavigationMode.Select_create_doc_destination,
                NavigationMode.Select_optimize_storage_backup_destination
        };

        ShadowAppFeatures.mIsTablet = false;

        for (NavigationMode navigationMode : NavigationMode.values()) {
            boolean expected = false;
            for (NavigationMode trueValue : trueList) {
                if (trueValue == navigationMode) {
                    expected = true;
                }
            }

            mNaviInfo.setNavigationMode(navigationMode);
            boolean actual = mNaviInfo.isLeftPanelDisabled();
            Assert.assertEquals(navigationMode.toString(), expected, actual);
        }
    }


    @Test
    public void testStartSelectionPos() {
        for (int i = 0; i < 10; i++) {
            mNaviInfo.setStartSelectionPos(i);

            int actual = mNaviInfo.getStartSelectionPos();
            Assert.assertEquals(i, actual);
        }
    }

    @Test
    public void testIsSearchMode() {
        mNaviInfo.setIsSearchMode(true);
        boolean actual = mNaviInfo.getIsSearchMode();

        Assert.assertTrue(actual);

        mNaviInfo.setIsSearchMode(false);
        actual = mNaviInfo.getIsSearchMode();
        Assert.assertFalse(actual);

    }

    @Test
    public void testContentObserver() {
        AbsContentObserverImp observer[] = {
                PowerMockito.mock(AbsContentObserverImp.class),
                PowerMockito.mock(AbsContentObserverImp.class),
                PowerMockito.mock(AbsContentObserverImp.class),
        };

        for (int i = 0; i < observer.length; i++) {
            Assert.assertEquals(i, mNaviInfo.getObserverSize());
            mNaviInfo.setContentObserver(observer[i]);
            Assert.assertEquals(i + 1, mNaviInfo.getObserverSize());
        }

        for (int i = 0; i < observer.length; i++) {
            AbsContentObserverImp obs = mNaviInfo.getContentObserver(i);
            Assert.assertSame(observer[i], obs);
        }

        mNaviInfo.clearObserver();
        Assert.assertEquals(0, mNaviInfo.getObserverSize());
    }


    @Test
    public void testNeedUpdateOptionsMenuAfterLoad() {
        boolean actual = mNaviInfo.needUpdateOptionsMenuAfterLoad();
        Assert.assertFalse(actual);

        for (NavigationMode navigationMode : NavigationMode.values()) {
            boolean expected = false;
            mNaviInfo.setNavigationMode(navigationMode);
            if (navigationMode == NavigationMode.Pick_files || navigationMode == NavigationMode.Pick_one_file) {
                expected = true;
            }
            actual = mNaviInfo.needUpdateOptionsMenuAfterLoad();
            Assert.assertEquals(expected, actual);
        }

        FileRecord record = new DownloadFileRecord("/test");
        mNaviInfo.setCurRecord(record);
        actual = mNaviInfo.needUpdateOptionsMenuAfterLoad();
        Assert.assertTrue(actual);


        record = new RecentFileRecord("/mnt/Test");
        mNaviInfo.setCurRecord(record);
        actual = mNaviInfo.needUpdateOptionsMenuAfterLoad();
        Assert.assertTrue(actual);

    }

}
